const RESOLVE = 'resolved'
const REJECT = 'rejected'
const PENDING = 'pending'

const handlePromise = (result, newPromise, resolve, reject) => {
    if (result === newPromise) {//返回自身没有意义
        throw new Error('can not return oneself')
    }
    if ((typeof result === 'object' && typeof result !== null || typeof result === 'function')) {
        let lock = false//当then为第三方写入的时候onResolve和Onreject同时只能有一个执行
        try {
            const then = result.then
            if (typeof then === 'function') {
                then.call(result, r => {
                    if (lock) return
                    handlePromise(r, newPromise, resolve, reject)
                    lock = true
                }, e => {
                    if (lock) return
                    reject(e)
                    lock = true
                })
            } else {
                resolve(result)

            }
        } catch (err) {
            reject(err)
        }

    } else {
        resolve(result)
    }
}
class JJPromise {
    status = PENDING
    result = undefined
    reason = undefined
    onResolvedArr = []
    onRejectedArr = []
    constructor(execution) {
        const resolve = (result) => {
            if (this.status === PENDING) {
                this.result = result
                this.status = RESOLVE
                this.onResolvedArr.map((fn) => fn())
            }
        }
        const reject = (reason) => {
            if (this.status === PENDING) {
                this.reason = reason
                this.status = REJECT
                this.onRejectedArr.map((fn) => fn())

            }
        }
        try {
            execution(resolve, reject)

        } catch (err) {
            reject(err)
        }
    }
    then(onResolved, onRejected) {
        onResolved = typeof onResolved === 'function' ? onResolved : (data) => data
        onRejected = typeof onRejected === 'function' ? onRejected : (err) => {
            throw new Error(err)//传入内容不对，抛出错误并reject出去
        }

        const newPromise = new JJPromise((resolve, reject) => {
            if (this.status === RESOLVE) {
                setTimeout(async () => {
                    try {
                        const result = onResolved(this.result)
                        handlePromise(result, newPromise, resolve, reject)
                    } catch (err) {
                        reject(err)
                    }

                }, 1000);
            }
            if (this.status === REJECT) {
                setTimeout(async () => {
                    try {
                        const result = onRejected(this.reason)
                        handlePromise(result, newPromise, resolve, reject)
                    } catch (err) {
                        reject(err)
                    }


                }, 1000);
            }
            if (this.status === PENDING) {
                this.onResolvedArr.push(() => {
                    try {
                        const result = onResolved(this.result)
                        handlePromise(result, newPromise, resolve, reject)
                    } catch (err) {
                        reject(err)
                    }

                })
                this.onRejectedArr.push(() => {
                    try {
                        const result = onRejected(this.reason)
                        handlePromise(result, newPromise, resolve, reject)
                    } catch (err) {
                        reject(err)
                    }

                })
            }
        })
        return newPromise
    }
    catch(onRejected) {
        return this.then(undefined, onRejected)
    }
}

module.exports = JJPromise


const myPromise = new JJPromise((resolve) => {
    console.log('Promise is about to be resolved');
    resolve();
    console.log('Promise is resolved, but this code still executes');
});
myPromise.then(() => {
    console.log('Promise is successfully resolved');
});

console.log('This code runs immediately after creating the Promise');